/**
 * 反射地板片元着色器
 * 实现地板的实时反射效果，包括：
 * - 波浪扰动（通过法线贴图）
 * - 反射纹理采样（通过反射矩阵）
 * - Fresnel 效果（边缘更反射）
 * - 动态粗糙度（基于距离的模糊）
 */

// 引入外部 GLSL 库
#include "/node_modules/lygia/lighting/fresnel.glsl"              // Fresnel 效果
#include "/node_modules/lygia/sample/bicubic.glsl"               // 双三次插值采样
#include "/node_modules/furina/sample/packedTexture2DLOD.glsl"   // Mipmap LOD 采样

// Shadertoy 风格的 uniform
uniform float iTime;        // 经过的时间
uniform vec2 iResolution;   // 视口分辨率
uniform vec2 iMouse;        // 鼠标位置

// 从顶点着色器传入的变量
varying vec2 vUv_;           // UV 纹理坐标
varying vec4 vWorldPosition; // 世界空间位置

// 自定义 uniform
uniform vec3 uColor;              // 地板基础颜色
uniform float uSpeed;             // 当前速度（影响波浪流动）
uniform mat4 uReflectMatrix;      // 反射矩阵（世界空间 → 反射纹理空间）
uniform sampler2D uReflectTexture;// 反射纹理（离屏渲染）
uniform float uReflectIntensity;  // 反射强度
uniform vec2 uMipmapTextureSize;  // Mipmap 纹理尺寸

void main(){
    vec2 p=vUv_;
    
    // ==================== 1. 计算表面法线（带波浪扰动） ====================
    // 使用世界坐标 XZ 平面作为 UV
    vec2 surfaceNormalUv=vWorldPosition.xz;
    // 根据速度让波浪沿 X 轴流动
    surfaceNormalUv.x+=iTime*uSpeed;
    // 采样法线贴图并转换到 [-1, 1] 范围
    vec3 surfaceNormal=texture(normalMap,surfaceNormalUv).rgb*2.-1.;
    // 调整通道顺序（R,B,G）
    surfaceNormal=surfaceNormal.rbg;
    // 归一化法线向量
    surfaceNormal=normalize(surfaceNormal);
    
    // ==================== 2. 计算视线方向和距离 ====================
    vec3 viewDir=vViewPosition; // 从相机到片元的向量
    float d=length(viewDir);    // 距离（用于透视修正）
    viewDir=normalize(viewDir); // 归一化视线方向
    
    // ==================== 3. 计算扰动偏移 ====================
    // 基于法线和距离的扰动，距离越近扰动越小
    vec2 distortion=surfaceNormal.xz*(.001+1./d);
    
    // ==================== 4. 计算反射纹理坐标 ====================
    // 将世界坐标转换到反射纹理空间
    vec4 reflectPoint=uReflectMatrix*vWorldPosition;
    // 透视除法
    reflectPoint=reflectPoint/reflectPoint.w;
    
    // ==================== 5. 采样反射纹理（带粗糙度模糊） ====================
    // 计算粗糙度 UV（也随速度流动）
    vec2 roughnessUv=vWorldPosition.xz;
    roughnessUv.x+=iTime*uSpeed;
    // 采样粗糙度贴图
    float roughnessValue=texture(roughnessMap,roughnessUv).r;
    // 调整粗糙度曲线
    roughnessValue=roughnessValue*(1.7-.7*roughnessValue);
    roughnessValue*=4.;
    // 将粗糙度映射为 Mipmap 级别
    float level=roughnessValue;
    // 最终 UV = 反射点 + 扰动
    vec2 finalUv=reflectPoint.xy+distortion;
    // 使用 LOD 采样反射纹理（粗糙度越高越模糊）
    vec3 reflectionSample=packedTexture2DLOD(uReflectTexture,finalUv,level,uMipmapTextureSize).rgb;
    // 应用反射强度
    reflectionSample*=uReflectIntensity;
    
    // ==================== 6. 混合基础颜色和反射 ====================
    vec3 col=uColor;           // 基础地板颜色
    // col+=reflectionSample;  // 可选：直接叠加
    col*=3.;                   // 提亮基础颜色
    // 计算 Fresnel 效果（边缘更反射）
    vec3 fres=fresnel(vec3(0.),vNormal,viewDir);
    // 根据 Fresnel 混合基础颜色和反射
    col=mix(col,reflectionSample,fres);
    
    // ==================== 7. 输出最终颜色 ====================
    // CSM 变量：设置漫反射颜色
    csm_DiffuseColor=vec4(col,1.);
}